类的运算符重载¶
逻辑思想:
运算符重载函数分为成员函数重载和非成员函数重载(即friend),两者的驱动生成会有所不同,主要表现在调用原函数上;首先在函数中将运算符重载函数分离出来;再将运算符重载函数区分为非成员函数(friend)和成员函数;然后分别进行具体的运算符进行驱动生成,不同的运算符会有不同处理。
问题: 为什么要将运算符重载函数与普通函数分离?
答: 在生成驱动时,运算符重载成员函数与类的普通成员函数区别在于类名以及参数,前者会有一个运算符的后缀,以及在成员函数的运算符重载中,有一个this指针隐含的传过去。
问题: 为什么要将运算符重载函数区分为非成员函数(friend)和成员函数?
答: 因为friend和普通函数的处理会有不同,主要表现在非成员重载函数正常会比成员重载函数多一个参数,成员函数的运算符重载中,有一个this指针隐含的传过去,以及在调用部分也会不同,成员重载函数可以直接使用类指针进行调用,而friend不一样。
问题: 为什么要对不同的操作符进行不同的处理?
答: 因为操作符直接的差异很大,有的并不需要参数,而需要参数的一部分是人为赋值的参数,一部分是系统参数,需要分开处理。
测试的源码¶
#pragma warning(disable:4996)
#include"json/json.h"
#include <iostream>
#include <fstream>
using namespace std;
#pragma once
class ClassOpertor
{
public:
ClassOpertor();
~ClassOpertor();
ClassOpertor operator- ();
bool operator<(const ClassOpertor& d);
ClassOpertor operator+(ClassOpertor&add);
ClassOpertor operator+(int b);
void displayDistance();
friend ClassOpertor operator+(const int b, ClassOpertor obj);
friend ClassOpertor operator+(const ClassOpertor& a, const ClassOpertor& b);
ostream &operator<<(ostream &output);
friend ostream &operator<<(ostream &output, const ClassOpertor &Dis);
ClassOpertor operator++();//前缀形式
ClassOpertor operator++(int);//后缀形式
int fun();
bool operator!();
void * operator new(size_t size);//一个参数,为size_t类型
void operator delete(void *ptr);// void 类型的指针作为参数
void operator=(const ClassOpertor &D);
void operator+=(const ClassOpertor &D);
int& operator[](int i);//下标
ClassOpertor& operator*();//指针
ClassOpertor* operator&();//取地址符
int operator()(int val);
ClassOpertor* operator->();
void operator delete[](void*, size_t size);
private:
int length;
int weight;
int arr[10];
ClassOpertor *persion;
public:
ClassOpertor(int length, int weight, int arr[10], bool Wings):length(length), weight(weight)
{
/* arr */
for(unsigned int size = 0; size < 10; size++)
{
this->arr[size] = arr[size];
}
}
};
成员函数的处理(篇幅原因,每种只列标志性的运算符重载的驱动代码)¶
1.算数运算符
+、-、*、/、%、++、--
加法(+)测试源码:
Operatortor Operatortor::operator+=(int len)
{
length += len;
return Operatortor();
}
加法(+)驱动:
int DriverClassOpertor::DriverClassOpertoroperator2(int times)
{
operator2Times = times;
const char* jsonFilePath = "drivervalue/ClassOpertor/operator2.json";
Json::Value Root;
Json::Reader _reader;
std::ifstream _ifs(jsonFilePath);
_reader.parse(_ifs, Root);
Json::Value _operator2_Root = Root["operator2" + std::to_string(times)];
Json::Value _addadd_Root = _operator2_Root["add"];
/* length */
int _addlength = _addadd_Root["length"].asInt();
/* weight */
int _addweight = _addadd_Root["weight"].asInt();
/* arr */
int _addarr[10];
for (int len = 0; len < 10; len++) {
_addarr[len] = _addadd_Root["arr"][len].asInt();
}
ClassOpertor _addadd(_addlength, _addweight, _addarr, false);
_ClassOpertor->operator+(_addadd);
return 0;
}
前置自增(++length)测试源码:
Operatortor Operatortor::operator++()
{
++length;
if (length >= 60)
{
++weight;
length -= 60;
}
return ClassOpertor();
}
前置自增(++length)驱动:
int DriverOperatortor::DriverOperatortoroperator8(int times)
{
_ClassOpertor->operator++();
return 0;
}
2.关系运算符
<、>、==、>=、<=、!=
小于号(<)源码:
bool Operatortor::operator<(const Operatortor & d)
{
if (length < d.length)
{
return true;
}
if (length == d.length && weight < d.weight)
{
return true;
}
return false;
}
小于号(<)驱动:
int DriverOperatortor::DriverOperatortoroperator1(int times)
{
operator1Times = times;
const char* jsonFilePath = "drivervalue/Operatortor/operator1.json";
Json::Value Root;
Json::Reader _reader;
std::ifstream _ifs(jsonFilePath);
_reader.parse(_ifs, Root);
Json::Value _operator1_Root = Root["operator1" + std::to_string(times)];
Json::Value _d_Root = _operator1_Root["d"];
/* length */
int _dlength = _d_Root["length"].asInt();
/* weight */
int _dweight = _d_Root["weight"].asInt();
Operatortor _dd(_dlength, _dweight, false);
// The Function of Class Call
_ClassOpertor->operator<(_dd);
return 0;
}
小于等于号(<=)驱动:
int DriverOperatortor::DriverOperatortoroperator1(int times)
{
operator1Times = times;
const char* jsonFilePath = "drivervalue/Operatortor/operator2.json";
Json::Value Root;
Json::Reader _reader;
std::ifstream _ifs(jsonFilePath);
_reader.parse(_ifs, Root);
Json::Value _operator2_Root = Root["operator2" + std::to_string(times)];
Json::Value _d_Root = _operator2_Root["d"];
/* length */
int _dlength = _d_Root["length"].asInt();
/* weight */
int _dweight = _d_Root["weight"].asInt();
Operatortor _dd(_dlength, _dweight, false);
// The Function of Class Call
_ClassOpertor->operator<=(_dd);
return 0;
}
3.赋值运算符
-=、+=、/=、*=、%=、&=、 ^=、 |=、 <<=、 >>=、=
=赋值运算符
int DriverClassOpertor::DriverClassOpertoroperator12(int times)
{
operator12Times = times;
const char* jsonFilePath = "drivervalue/ClassOpertor/operator12.json";
Json::Value Root;
Json::Reader _reader;
std::ifstream _ifs(jsonFilePath);
_reader.parse(_ifs, Root);
Json::Value _operator12_Root = Root["operator12" + std::to_string(times)];
Json::Value _DD_Root = _operator12_Root["D"];
/* length */
int _Dlength = _DD_Root["length"].asInt();
/* weight */
int _Dweight = _DD_Root["weight"].asInt();
/* arr */
int _Darr[10];
for (int len = 0; len < 10; len++) {
_Darr[len] = _DD_Root["arr"][len].asInt();
}
ClassOpertor _DD(_Dlength, _Dweight, _Darr, false);
//The Function of Class Call
_ClassOpertor->operator=(_DD);
return 0;
}
+=赋值运算符
int DriverClassOpertor::DriverClassOpertoroperator13(int times)
{
operator13Times = times;
const char* jsonFilePath = "drivervalue/ClassOpertor/operator13.json";
Json::Value Root;
Json::Reader _reader;
std::ifstream _ifs(jsonFilePath);
_reader.parse(_ifs, Root);
Json::Value _operator13_Root = Root["operator13" + std::to_string(times)];
Json::Value _DD_Root = _operator13_Root["D"];
/* length */
int _Dlength = _DD_Root["length"].asInt();
/* weight */
int _Dweight = _DD_Root["weight"].asInt();
/* arr */
int _Darr[10];
for (int len = 0; len < 10; len++) {
_Darr[len] = _DD_Root["arr"][len].asInt();
}
ClassOpertor _DD(_Dlength, _Dweight, _Darr, false);
//The Function of Class Call
_ClassOpertor->operator+=(_DD);
return 0;
}
4.单目运算符
+(正)、-(负)、*(指针)、&(取地址)
&(取地址)
int DriverClassOpertor::DriverClassOpertoroperator16(int times)
{
operator16Times = times;
const char* jsonFilePath = "drivervalue/ClassOpertor/operator16.json";
Json::Value Root;
Json::Reader _reader;
std::ifstream _ifs(jsonFilePath);
_reader.parse(_ifs, Root);
Json::Value _operator16_Root = Root["operator16" + std::to_string(times)];
_ClassOpertor->operator&();
return 0;
}
-(负)运算符
int DriverClassOpertor::DriverClassOpertoroperator0(int times)
{
_ClassOpertor->operator-();
return 0;
}
5.逻辑运算符和位运算符
&、|、^、&&、||、!、<<(左移)、>>(右移)、~(按位取反)
&&和||不建议重载运算符。
问题: 为什么不建议重载&&和||?
答: 逻辑&&和逻辑||运算符是可以重载的,但是重载不能实现逻辑&&和逻辑||运算符的短路功能。
!=(逻辑非运算符)
int DriverClassOpertor::DriverClassOpertoroperator9(int times)
{
operator9Times = times;
const char* jsonFilePath = "drivervalue/ClassOpertor/operator9.json";
Json::Value Root;
Json::Reader _reader;
std::ifstream _ifs(jsonFilePath);
_reader.parse(_ifs, Root);
Json::Value _operator9_Root = Root["operator9" + std::to_string(times)];
_ClassOpertor->operator!();
return 0;
}
6.流运算符
<<、>>
对于C++的输入输出流的重载函数来说,参数output我们在驱动赋值时并不需要去定义和赋值,可以直接使用cout,即标准c++的输出函数。
<<输出流的源码:
ostream & ClassOpertor::operator<<(ostream & output)
{
return output;
}
<<输出流运算符
int DriverClassOpertor::DriverClassOpertoroperator5(int times)
{
_ClassOpertor->operator<<(cout);
return 0;
}
7.空间申请与释放
new、delete、new[]、delete[]
new运算符
int DriverClassOpertor::DriverClassOpertoroperator10(int times)
{
operator10Times = times;
const char* jsonFilePath = "drivervalue/ClassOpertor/operator10.json";
Json::Value Root;
Json::Reader _reader;
std::ifstream _ifs(jsonFilePath);
_reader.parse(_ifs, Root);
Json::Value _operator10_Root = Root["operator10" + std::to_string(times)];
/* size */
unsigned int _size = _operator10_Root["size"].asUInt();
_ClassOpertor->operator new(_size);
return 0;
}
delete运算符
int DriverClassOpertor::DriverClassOpertoroperator11(int times)
{
operator11Times = times;
const char* jsonFilePath = "drivervalue/ClassOpertor/operator11.json";
Json::Value Root;
Json::Reader _reader;
std::ifstream _ifs(jsonFilePath);
_reader.parse(_ifs, Root);
Json::Value _operator11_Root = Root["operator11" + std::to_string(times)];
/* ptr */
void* _ptr = nullptr;
//The Function of Class Call
_ClassOpertor->operator delete(_ptr);
return 0;
}
8.特殊运算符
->(类成员访问运算符)、()(函数运算符)、[](下标运算符)、co_await、,(逗号))
[]下标运算符源码
int & ClassOpertor::operator[](int i)
{
int SIZE = 10;
if (i > SIZE)
{
cout << "索引超过最大值" << endl;
return arr[0];
}
return arr[i];
}
[]下标运算符驱动
int DriverClassOpertor::DriverClassOpertoroperator14(int times)
{
operator14Times = times;
const char* jsonFilePath = "drivervalue/ClassOpertor/operator14.json";
Json::Value Root;
Json::Reader _reader;
std::ifstream _ifs(jsonFilePath);
_reader.parse(_ifs, Root);
Json::Value _operator14_Root = Root["operator14" + std::to_string(times)];
/* i */
int _i = _operator14_Root["i"].asInt();
_ClassOpertor->operator[](_i);
return 0;
}
()函数运算符
int DriverClassOpertor::DriverClassOpertoroperator17(int times)
{
operator17Times = times;
const char* jsonFilePath = "drivervalue/ClassOpertor/operator17.json";
Json::Value Root;
Json::Reader _reader;
std::ifstream _ifs(jsonFilePath);
_reader.parse(_ifs, Root);
Json::Value _operator17_Root = Root["operator17" + std::to_string(times)];
/* val */
int _val = _operator17_Root["val"].asInt();
_ClassOpertor->operator()(_val);
return 0;
}
->(类成员访问符)
int DriverClassOpertor::DriverClassOpertoroperator9(int times)
{
_ClassOpertor->operator->();
return 0;
}
,(逗号运算符)
int DriverClassOpertor::DriverClassOpertoroperator2(int times)
{
operator2Times = times;
const char* jsonFilePath = "drivervalue/ClassOpertor/operator18.json";
Json::Value Root;
Json::Reader _reader;
std::ifstream _ifs(jsonFilePath);
_reader.parse(_ifs, Root);
Json::Value _operator2_Root = Root["operator2" + std::to_string(times)];
Json::Value _rdd_Root = _operator2_Root["add"];
/* length */
int _rddlength = _rdd_Root["length"].asInt();
/* weight */
int _rddweight = _rdd_Root["weight"].asInt();
/* arr */
int _addarr[10];
for (int len = 0; len < 10; len++) {
_rddarr[len] = _rdd_Root["arr"][len].asInt();
}
ClassOpertor _rdd(_rddlength, _rddweight, _rddarr, false);
_ClassOpertor->operator->(_rdd);
return 0;
}
非成员函数(friend)的处理¶
非成员的重载函数在驱动生成上和成员函数区别并不是很大,主要表现在以下两点:
1)函数参数上,作为成员函数重载时,,有一个this指针隐含的传过去,不需要驱动中给它额外赋值;非成员的重载函数则没有,相同符号的重载,后者会比前者多一个参数,这里需要驱动给它赋值。
2)调用原函数上,作为成员函数重载时,可以使用类指针进行调用重载函数,非成员的重载函数则不需要,可以直接使用。